package br.com.lazyprogrammer.social.infestit.localization;

import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;

import br.com.lazyprogrammer.social.infestit.R;
import br.com.lazyprogrammer.social.infestit.localization.exception.LocalizationTimeOutException;

public class LocalizationDAO implements LocationListener {
	
	private LocationChangedListener callbackListener;
	
	private LocationManager locationManager;
	
	private boolean once;
	
	private boolean locationFound = false;
	
	LocalizationDAO() {
		super();
	}
	
	/**
	 * Register a LocationListener for each 10 seconds or 10 meters
	 * 
	 * @param context
	 * @param callbackListener
	 */
	public void requestLocationUpdate(Context context,LocationChangedListener callbackListener) {
		requestLocationUpdate(context, callbackListener,false);
	}
	
	/**
	 * Register a LocationListener for only one change
	 * 
	 * @param context
	 * @param callbackListener
	 */
	public void requestLocationOnce(Context context,LocationChangedListener callbackListener) {
		requestLocationUpdate(context, callbackListener,true);
	}
	
	/**
	 * Method that make the request on the LocationListener, for one or more responses.
	 * 
	 * @param context
	 * @param callbackListener
	 * @param once
	 */
	private void requestLocationUpdate(final Context context,final LocationChangedListener callbackListener,boolean once) {
		this.callbackListener = callbackListener;
		this.once = once;
		locationManager = (LocationManager) context
				.getSystemService(Context.LOCATION_SERVICE);
		locationManager.removeUpdates(this);
		
		Criteria criteria = new Criteria();
		String provider;
		
		if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
			provider = LocationManager.NETWORK_PROVIDER;
			locationManager.requestLocationUpdates(provider, 10000, 10, this);
			locationFound = false;
		} else {
			criteria.setAccuracy(Criteria.ACCURACY_FINE);
			provider = locationManager.getBestProvider(criteria, true);
			locationManager.requestLocationUpdates(provider, 10000, 10, this);
		}
		
		
		
		new Handler().postDelayed(new Runnable(){

			@Override
			public void run() {
				if (!locationFound) {
					if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
						if (locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER) != null) {
							callbackListener.onLocationChanged(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
							return;
						}
					} else {
						Criteria criteria = new Criteria();
						if (locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true)) != null) {
							callbackListener.onLocationChanged(locationManager.getLastKnownLocation(locationManager.getBestProvider(criteria, true)));
							return;
						}
					}
					new LocalizationTimeOutException(
							context.getString(R.string.exception_get_location_timeout))
							.showErrorDialog(context);
					stopUpdates();
					callbackListener.onTimeout();
				}
			}
			
		},15000);
	}
	
	public void stopUpdates() {
		if (locationManager != null) {
			locationManager.removeUpdates(this);
		}
	}

	@Override
	public void onLocationChanged(Location location) {
		locationFound = true;
		if (once) {
			stopUpdates();
		}
		callbackListener.onLocationChanged(location);
	}

	@Override
	public void onProviderDisabled(String provider) {
		android.util.Log.i("PROVIDER DISABLE",provider);
	}

	@Override
	public void onProviderEnabled(String provider) {
		android.util.Log.i("PROVIDER ENABLE",provider);
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		android.util.Log.i("PROVIDER CHANGE",provider);
	}
	
	public interface LocationChangedListener {
		public void onLocationChanged(Location location);
		public void onTimeout();
	}

}
